﻿
namespace Octopus.HpcPowerShell

(*
#r "System.Management.Automation"

#quit
*)

open System.Management.Automation
open System.Management.Automation.Host
open System.Management.Automation.Runspaces



type private MyAuthorizationManager (shellId:string) =
  inherit AuthorizationManager(shellId)
  
  override x.ShouldRun (commandInfo:CommandInfo, origin:CommandOrigin, host:PSHost, reason:byref<System.Exception>) =
    reason <- null
    true



type HpcPowerShell () =
  let ps = PowerShell.Create()
  let psInvoke() =
    try
      let res = ps.Invoke()
      if ps.Streams.Error.Count > 0 then
        let e = ps.Streams.Error.[0].Exception
        ps.Streams.Error.Clear()
        raise e
      res
    finally
      ps.Commands.Clear()

  do
    let t = typeof<RunspaceConfiguration>
    let f = t.GetField("_authorizationManager", System.Reflection.BindingFlags.Instance ||| System.Reflection.BindingFlags.NonPublic)
    f.SetValue(ps.Runspace.RunspaceConfiguration, new MyAuthorizationManager("Microsoft.PowerShell"))
    
    let hpc2008R2Path = @"C:\Program Files\Microsoft HPC Pack 2008 R2\Bin"

    let myResolveEventHandler (sender:obj) (args:System.ResolveEventArgs) =
        let argName = if not(args.Name.Contains(",")) then args.Name
                      else args.Name.Substring(0,args.Name.IndexOf(","))
        let strTempAssmbPath = sprintf "%s\\%s.dll" hpc2008R2Path argName
        System.Reflection.Assembly.LoadFrom(strTempAssmbPath)
        
    System.AppDomain.CurrentDomain.add_AssemblyResolve(new System.ResolveEventHandler(myResolveEventHandler))
    
    ps.AddCommand("Add-PSSnapIn").AddArgument("Microsoft.Hpc") |> ignore
    ps.Invoke() |> ignore

    if ps.Streams.Error.Count > 0 then
      ps.Dispose()
      raise (ps.Streams.Error.[0].Exception)

    ps.Commands.Clear()
    ps.Streams.Error.Clear()


  interface System.IDisposable with
    override x.Dispose() =
      ps.Dispose()


  member x.GetNodeState (nodeName:string) =
    ps.AddCommand("Get-HpcNode") |> ignore
    ps.AddArgument(nodeName) |> ignore
    let res = psInvoke()
    res.[0].Properties.["NodeState"].Value.ToString()
    
  member x.SetNodeOnline (nodeName:string) =
    ps.AddCommand("Set-HpcNodeState") |> ignore
    ps.AddParameter("Name", nodeName) |> ignore
    ps.AddParameter("State", "Online") |> ignore
    psInvoke() |> ignore

  member x.SetNodeOffline (nodeName:string) =
    ps.AddCommand("Set-HpcNodeState") |> ignore
    ps.AddParameter("Name", nodeName) |> ignore
    ps.AddParameter("State", "Offline") |> ignore
    psInvoke() |> ignore

  member x.Assign_HpcNodeTemplate (nodeName:string) (templateName:string) =
    ps.AddCommand("Assign-HpcNodeTemplate") |> ignore
    ps.AddParameter("Name", templateName) |> ignore
    ps.AddParameter("NodeName", nodeName) |> ignore
    ps.AddParameter("Confirm", new SwitchParameter(false)) |> ignore
    psInvoke() |> ignore
 
  member x.Import_HpcNodeXml (xmlPath:string) =
    ps.AddCommand("Import-HpcNodeXml") |> ignore
    ps.AddParameter("Path", xmlPath) |> ignore
    ps.AddParameter("Confirm", new SwitchParameter(false)) |> ignore
    psInvoke() |> ignore
